package cn.juque.jdfsystem.interceptor;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.extra.spring.SpringUtil;
import cn.juque.common.base.BaseConstants;
import cn.juque.common.base.BaseOperator;
import cn.juque.common.base.BaseResponseVO;
import cn.juque.common.constants.StringConstants;
import cn.juque.common.constants.TreeNodeConstants;
import cn.juque.common.thread.BaseOperatorThreadLocal;
import cn.juque.common.utils.FastJsonUtil;
import cn.juque.jdfsystem.cache.PlatformInfoCache;
import cn.juque.jdfsystem.contants.BusinessConstants;
import cn.juque.jdfsystem.entity.PlatformInfo;
import cn.juque.jdfsystem.enums.JdfSystemMsgEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Date;

/**
 * @author juque
 * @version 1.0.0
 * <ul>
 *     <li>CheckApiInterceptor</li>
 * </ul>
 * @date 2023-01-11 16:03:56
 **/
@Slf4j
public class CheckApiInterceptor implements HandlerInterceptor {

    private static final HMac H_MAC = new HMac(HmacAlgorithm.HmacMD5, BusinessConstants.H_MAC_KEY.getBytes(StandardCharsets.UTF_8));

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        BaseOperator baseOperator = new BaseOperator();
        baseOperator.setOrgIdList(CollUtil.newArrayList(TreeNodeConstants.ROOT_CHAR));
        baseOperator.setOperatorId(BaseConstants.ADMIN);
        baseOperator.setOperatorTime(new Date());

        BaseOperatorThreadLocal baseOperatorThreadLocal = SpringUtil.getBean(BaseOperatorThreadLocal.class);
        baseOperatorThreadLocal.set(baseOperator);

        // 验证签名
        PlatformInfoCache platformInfoCache = SpringUtil.getBean(PlatformInfoCache.BEAN);
        String platformId = request.getHeader(StringConstants.PLATFORM_ID);
        PlatformInfo platformInfo = platformInfoCache.getPlatformInfo(platformId);
        if (null == platformInfo) {
            BaseResponseVO<Boolean> responseVO = new BaseResponseVO<>(JdfSystemMsgEnum.PLATFORM_CHECK_FAIL, false);
            this.print(response, responseVO);
            return false;
        }
        String secret = platformInfo.getSecret();
        String signature = request.getHeader(BusinessConstants.SIGNATURE);
        boolean flag = H_MAC.verify(HexUtil.decodeHex(signature), H_MAC.digest(secret));
        if (!flag) {
            BaseResponseVO<Boolean> responseVO = new BaseResponseVO<>(JdfSystemMsgEnum.SIGNATURE_CHECK_FAIL, false);
            this.print(response, responseVO);
            return false;
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        BaseOperatorThreadLocal baseOperatorThreadLocal = SpringUtil.getBean(BaseOperatorThreadLocal.class);
        baseOperatorThreadLocal.remove();
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    /**
     * 输出消息
     *
     * @param response   HttpServletResponse
     * @param responseVO BaseResponseVO
     */
    private void print(HttpServletResponse response, BaseResponseVO<?> responseVO) {
        response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        response.setContentType("application/json; charset=utf-8");
        try (PrintWriter out = response.getWriter()) {
            out.write(FastJsonUtil.toJsonString(responseVO));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
}
